package com.yanfan;

import com.alibaba.fastjson2.JSONObject;
import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.RemoteDevice;
import com.serotonin.bacnet4j.exception.BACnetException;
import com.serotonin.bacnet4j.exception.PropertyValueException;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.type.enumerated.ObjectType;
import com.serotonin.bacnet4j.type.enumerated.PropertyIdentifier;
import com.serotonin.bacnet4j.type.primitive.ObjectIdentifier;
import com.serotonin.bacnet4j.util.PropertyReferences;
import com.serotonin.bacnet4j.util.PropertyValues;
import com.serotonin.bacnet4j.util.ReadListener;
import com.serotonin.bacnet4j.util.RequestUtils;


import java.util.ArrayList;
import java.util.List;

public class BacnetDataRetriever {

    public static void main(String[] args) throws Exception {
        // 创建网络对象
        IpNetwork ipNetwork = new IpNetworkBuilder()
                .withLocalBindAddress("192.168.23.7")
                .withSubnet("255.255.255.0", 24)
                .withPort(47808)
                .withReuseAddress(true)
                .build();

        // 创建虚拟的本地设备并初始化
        LocalDevice localDevice = new LocalDevice(223, new DefaultTransport(ipNetwork));
        localDevice.initialize();
        localDevice.startRemoteDeviceDiscovery();

        // 获取远程设备
        Integer remoteDeviceId = 2605;
        RemoteDevice remoteDevice = localDevice.getRemoteDeviceBlocking(remoteDeviceId);

        // 获取远程设备的标识符对象
        List<ObjectIdentifier> objectList = RequestUtils.getObjectList(localDevice, remoteDevice).getValues();

        List<ObjectIdentifier> aiList = new ArrayList<>();
        List<ObjectIdentifier> avList = new ArrayList<>();


        // 过滤对象标识符列表
        for (ObjectIdentifier oi : objectList) {
            System.out.println(oi);
            if (oi.getObjectType().equals(ObjectType.analogValue)) {
                aiList.add(new ObjectIdentifier(ObjectType.analogValue, oi.getInstanceNumber()));
            }
            if (oi.getObjectType().equals(ObjectType.binaryOutput)) {
                avList.add(new ObjectIdentifier(ObjectType.binaryOutput, oi.getInstanceNumber()));
            }
        }

        // 读取属性值
        PropertyValues pvAiObjectName = readValueByPropertyIdentifier(localDevice, remoteDevice, aiList, null, PropertyIdentifier.objectName);
        PropertyValues pvAiPresentValue = readValueByPropertyIdentifier(localDevice, remoteDevice, aiList, null, PropertyIdentifier.presentValue);
        PropertyValues pvAiDescription = readValueByPropertyIdentifier(localDevice, remoteDevice, aiList, null, PropertyIdentifier.description);

        PropertyValues pvAvObjectName = readValueByPropertyIdentifier(localDevice, remoteDevice, avList, null, PropertyIdentifier.objectName);
        PropertyValues pvAvPresentValue = readValueByPropertyIdentifier(localDevice, remoteDevice, avList, null, PropertyIdentifier.presentValue);
        PropertyValues pvAvDescription = readValueByPropertyIdentifier(localDevice, remoteDevice, avList, null, PropertyIdentifier.description);

        JSONObject jsonObject = new JSONObject();
        List<JSONObject> aiDataList = new ArrayList<>();
        for (ObjectIdentifier oi : aiList) {
            JSONObject aiData = new JSONObject();
            aiData.put("objectType", oi.getObjectType().toString());
            aiData.put("instanceNumber", oi.getInstanceNumber());
            aiData.put("tagNumber", pvAiObjectName.get(oi, PropertyIdentifier.objectName).toString());
            aiData.put("presentValue", pvAiPresentValue.get(oi, PropertyIdentifier.presentValue).toString());
            aiData.put("description", pvAiDescription.get(oi, PropertyIdentifier.description).toString());
            aiDataList.add(aiData);
        }
        jsonObject.put("analogInputData", aiDataList);

        List<JSONObject> avDataList = new ArrayList<>();
        for (ObjectIdentifier oi : avList) {
            JSONObject avData = new JSONObject();
            avData.put("objectType", oi.getObjectType().toString());
            avData.put("instanceNumber", oi.getInstanceNumber());
            avData.put("tagNumber", pvAvObjectName.get(oi, PropertyIdentifier.objectName).toString());
            avData.put("presentValue", pvAvPresentValue.get(oi, PropertyIdentifier.presentValue).toString());
            avData.put("description", pvAvDescription.get(oi, PropertyIdentifier.description).toString());
            avDataList.add(avData);
        }
        jsonObject.put("analogValueData", avDataList);
        // 关闭本地设备
        localDevice.terminate();

    }

    public static PropertyValues readValueByPropertyIdentifier(final LocalDevice localDevice, final RemoteDevice d,
                                                               final List<ObjectIdentifier> ois, final ReadListener callback, PropertyIdentifier propertyIdentifier) throws BACnetException {
        if (ois.size() == 0) {
            return new PropertyValues();
        }

        final PropertyReferences refs = new PropertyReferences();
        for (final ObjectIdentifier oid : ois) {
            refs.add(oid, propertyIdentifier);
        }

        return RequestUtils.readProperties(localDevice, d, refs, false, callback);
    }
}
